package com.etcn.common.utils.http;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

import com.etcn.common.utils.JsonHandler;

import ch.qos.logback.classic.Logger;

/**
 * 发送http请求工具类
 * 
 * @author guozc
 */
public class HttpSend {

	/**
	 * 工具 logger
	 */
	protected Logger utilLogger = (Logger) LoggerFactory.getLogger("util_file_log");

	/**
	 * 异常logger
	 */
	protected Logger errorLogger = (Logger) LoggerFactory.getLogger("error_file_log");

	// 返回结果
	private Map<String, Object> ret = new HashMap<String, Object>();
	// 请求头
	private Map<String, String> headers = new HashMap<String, String>();

	private static final int TIME_OUT = 10 * 10000000; // 超时时间
	private static final String CHARSET = "utf-8"; // 设置编码
	public static final String SUCCESS = "1";
	public static final String FAILURE = "0";

	/**
	 * @Description: 设置http header
	 * @param: headName
	 *             head名称 headValue head值
	 */
	public void setHeader(String headName, String headValue) {
		headers.put(headName, headValue);
	}

	/**
	 * 发送http请求
	 * 
	 * @param reqUrl
	 *            发送请求的 URL
	 * @param param
	 *            请求参数
	 * @return 成功或失败 true/fase
	 */
	public boolean sendRequest(String reqUrl, Map<String, Object> jsonparams, String strparams, String requestType,
			String contentType) throws Exception {
		StringBuffer logs = new StringBuffer();
		HttpURLConnection urlConn = null;
		PrintWriter out = null;
		BufferedReader in = null;
		StringBuffer retMsg = new StringBuffer();
		Integer retCode = null;
		String param = null;
		// 参数是json类型
		if (contentType != null && contentType.equals("application/json")) {
			param = JsonHandler.build().toJson(jsonparams);
		}
		// 参数是字符串类型(account=17526745&pwd=789789&product=12这种的)
		else {
			param = strparams;
		}
		logs.append("------------------发送 ");
		logs.append(requestType);
		logs.append(" 请求------------------");
		logs.append("\r\nurl:\r\n");
		logs.append(reqUrl);
		logs.append("\r\n参数:\r\n");
		logs.append(param);
		try {
			URL url = new URL(reqUrl);
			urlConn = (HttpURLConnection) url.openConnection();
			// 设置通用的请求属性
			urlConn.setRequestProperty("accept", "*/*");
			urlConn.setRequestProperty("connection", "Keep-Alive");
			if (contentType != null) {
				urlConn.setRequestProperty("Content-Type", contentType);
			}
			urlConn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			urlConn.setDoInput(true);
			urlConn.setDoOutput(true);
			urlConn.setRequestMethod(requestType);
			urlConn.setUseCaches(false);
			// 设置header
			List<String> headerNames = new ArrayList<String>(headers.keySet());
			for (String headerName : headerNames) {
				urlConn.setRequestProperty(headerName, headers.get(headerName));
			}
			//
			urlConn.connect();
			if (!requestType.equals("GET")) {
				out = new PrintWriter(urlConn.getOutputStream());
				out.print(param);
				out.flush();
			}
			retCode = urlConn.getResponseCode();
			ret.put("retCode", retCode);
			// 去的返回信息
			if (retCode >= 400) {
				in = new BufferedReader(new InputStreamReader(urlConn.getErrorStream()));
			} else {
				in = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
			}
			String line;
			while ((line = in.readLine()) != null) {
				retMsg.append(line);
			}
			ret.put("retMsg", retMsg.toString());
		} catch (Exception e) {
			errorLogger.error("发送 请求出现异常!");
			e.printStackTrace();
			ret.put("retCode", HttpStatus.INTERNAL_SERVER_ERROR.value());
		} finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
				if (urlConn != null) {
					urlConn.disconnect();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		logs.append("\r\n返回值:\r\nretCode=>");
		logs.append(retCode);
		logs.append(" \r\nretMsg=>");
		logs.append(retMsg);
		logs.append("\r\n--------------------请求完毕---------------------");
		utilLogger.info(logs.toString());
		return success();
	}

	/**
	 * 文件上传
	 * @param file 文件
	 * @param RequestURL 请求服务器地址
	 * @param fileFormName 文件表单名称
	 * @return 上传结果
	 */
	public boolean uploadFile(File file, String RequestURL,String fileFormName) {
		StringBuffer retMsg = new StringBuffer();
		Integer retCode = null;
		BufferedReader in = null;
		String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
		String PREFIX = "--", LINE_END = "\r\n";
		String CONTENT_TYPE = "multipart/form-data"; // 内容类型
		try {
			URL url = new URL(RequestURL);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setReadTimeout(TIME_OUT);
			conn.setConnectTimeout(TIME_OUT);
			conn.setDoInput(true); // 允许输入流
			conn.setDoOutput(true); // 允许输出流
			conn.setUseCaches(false); // 不允许使用缓存
			conn.setRequestMethod("POST"); // 请求方式
			conn.setRequestProperty("Charset", CHARSET); // 设置编码
			conn.setRequestProperty("connection", "keep-alive");
			conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
			if (file != null) {
				/**
				 * 当文件不为空，把文件包装并且上传
				 */
				OutputStream outputSteam = conn.getOutputStream();
				DataOutputStream dos = new DataOutputStream(outputSteam);
				StringBuffer sb = new StringBuffer();
				sb.append(PREFIX);
				sb.append(BOUNDARY);
				sb.append(LINE_END);
				/**
				 * 这里重点注意： name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
				 * filename是文件的名字，包含后缀名的 比如:abc.png
				 */
				sb.append("Content-Disposition: form-data; name=\""+fileFormName+"\"; filename=\"" + file.getName() + "\""
						+ LINE_END);
				sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END);
				sb.append(LINE_END);
				dos.write(sb.toString().getBytes());
				InputStream is = new FileInputStream(file);
				byte[] bytes = new byte[1024];
				int len = 0;
				while ((len = is.read(bytes)) != -1) {
					dos.write(bytes, 0, len);
				}
				is.close();
				dos.write(LINE_END.getBytes());
				byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
				dos.write(end_data);
				dos.flush();
				/**
				 * 获取响应码 200=成功 当响应成功，获取响应的流
				 */
				retCode = conn.getResponseCode();
				// 去的返回信息
				if (retCode >= 400) {
					in = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
				} else {
					in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
				}
				String line;
				while ((line = in.readLine()) != null) {
					retMsg.append(line);
				}
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return success();
	}

	public boolean sendJsonPost(String reqUrl, Map<String, Object> params) throws Exception {
		return sendRequest(reqUrl, params, null, "POST", "application/json");
	}

	public boolean sendNoJsonPost(String reqUrl, String params) throws Exception {
		return sendRequest(reqUrl, null, params, "POST", null);
	}

	public boolean sendJsonPut(String reqUrl, Map<String, Object> params) throws Exception {
		return sendRequest(reqUrl, params, null, "PUT", "application/json");
	}

	public boolean sendGet(String reqUrl) throws Exception {
		return sendRequest(reqUrl, null, null, "GET", null);
	}

	public boolean success() {
		Integer retCode = (Integer) ret.get("retCode");
		if (retCode == HttpStatus.OK.value()) {
			return true;
		}
		return false;
	}

	public String returnMsg() {
		Object msg = ret.get("retMsg");
		if (msg == null) {
			return null;
		}
		return (String) msg;
	}

	public Integer httpStatus() {
		return (Integer) ret.get("retCode");
	}

}
